`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company: 
// Engineer: Rohit Kulkarni, Vedang Vaidya
// 
// Create Date:    10:07:39 04/04/2014 
// Design Name: 
// Module Name:    Motion_Indicator_FSM 
// Project Name: 
// Target Devices: 
// Tool versions: 
// Description: 
//
// Dependencies: 
//
// Revision: 
// Revision 0.01 - File Created
// Additional Comments: 
//
//////////////////////////////////////////////////////////////////////////////////
module Motion_Indicator_FSM(
	input clk,
	input reset,
	input  		[2:0] motion_mode,		// 3 bit motion mode as input for the seven possible motion modes
	output reg 	[4:0] motion_pos 		// 5 bits indicate the motion position	
    );
				
	// Rojobot's Motion Modes
	parameter STOP 			= 3'b000;
	parameter TURN_RIGHT_1X = 3'b001;
	parameter TURN_RIGHT_2X = 3'b010;
	parameter TURN_LEFT_1X 	= 3'b011;
	parameter TURN_LEFT_2X 	= 3'b100;
	parameter FORWARD 		= 3'b101;
	parameter REVERSE 		= 3'b110;
	
	//State Declarations using one hot encoding 
	 parameter
		RESET					= 8'b00000001,
		SEG_G_STEADY		= 8'b00000010,
		CHASE_CLK_5Hz		= 8'b00000100,
		CHASE_CLK_10Hz		= 8'b00001000,
		CHASE_ANTICLK_5Hz	= 8'b00010000,
		CHASE_ANTICLK_10Hz= 8'b00100000,
		BLINK_SEG_A_1Hz	= 8'b01000000,
		BLINK_SEG_D_1Hz	= 8'b10000000;
	 
	 //Outputs 
	 parameter
		seg_a		= 5'd16,
		seg_b		= 5'd17,
		seg_c		= 5'd18,
		seg_d		= 5'd19,
		seg_e		= 5'd20,
		seg_f		= 5'd21,
		seg_g		= 5'd22,
		blank		= 5'd29;
		
	//For generating 5Hz frequency clock	
   parameter  simulate = 0;
   localparam rojobot_cnt_5Hz = simulate ? 26'd5			// rojobot clock when simulating
                                      : 26'd19_999_999; // rojobot count when running on HW (5Hz)
	
	localparam rojobot_cnt_1Hz = simulate ? 27'd5			// rojobot clock when simulating
                                      : 27'd49_999_999; // rojobot count when running on HW (5Hz)

	localparam rojobot_cnt_10Hz = simulate ? 26'd5			// rojobot clock when simulating
                                      : 26'd9_999_999; // rojobot count when running on HW (5Hz)

	
	//internal registers	
	reg [25:0]	ck_count_5Hz = 0;	//clock divider counter
	reg tick5hz;						// 5 Hz clock enable
	reg [26:0]	ck_count_1Hz = 0;	//clock divider counter
	reg tick1hz;						// 1 Hz clock enable
	reg [25:0]	ck_count_10Hz = 0;//clock divider counter
	reg tick10hz;						// 10 Hz clock enable

	reg seg_g_steady			= 0;
	reg chase_clk_5Hz			= 0;
	reg chase_clk_10Hz		= 0;	
	reg chase_anticlk_5Hz 	= 0;	
	reg chase_anticlk_10Hz	= 0;
	reg blink_seg_A			= 0;
	reg blink_seg_D			= 0;
	reg [4:0] motion_pos_temp = seg_a;	
	
	always @(posedge clk or posedge reset)
	begin
		if (reset)
		begin
			motion_pos <= seg_g;
		end
		else
		begin
			case (motion_mode)
				STOP: 	motion_pos <= seg_g;
				
				FORWARD:
				if(tick1hz)
				begin
					case(motion_pos_temp)
						seg_a: motion_pos_temp = blank;
						blank: motion_pos_temp = seg_a;
						default: motion_pos_temp = seg_a;
					endcase
					motion_pos <= motion_pos_temp;
				end
				
				REVERSE:
				if(tick1hz)
				begin
					case(motion_pos_temp)
						seg_d: motion_pos_temp = blank;
						blank: motion_pos_temp = seg_d;
						default: motion_pos_temp = seg_d;
					endcase
					motion_pos <= motion_pos_temp;
				end

				TURN_RIGHT_1X:
				if(tick5hz)
				begin
					case(motion_pos_temp)
						seg_a: motion_pos_temp = seg_b;
						seg_b: motion_pos_temp = seg_c;
						seg_c: motion_pos_temp = seg_d;
						seg_d: motion_pos_temp = seg_e;
						seg_e: motion_pos_temp = seg_f;
						seg_f: motion_pos_temp = seg_a;
						default: motion_pos_temp = seg_a;	
					endcase
					motion_pos <= motion_pos_temp;
				end
				
				TURN_LEFT_1X:
				if(tick5hz)
				begin
					case(motion_pos_temp)
						seg_a: motion_pos_temp = seg_f;
						seg_f: motion_pos_temp = seg_e;
						seg_e: motion_pos_temp = seg_d;
						seg_d: motion_pos_temp = seg_c;
						seg_c: motion_pos_temp = seg_b;
						seg_b: motion_pos_temp = seg_a;
						default: motion_pos_temp = seg_a;	
					endcase
					motion_pos <= motion_pos_temp;
				end

				TURN_RIGHT_2X:
				if(tick10hz)
				begin
					case(motion_pos_temp)
						seg_a: motion_pos_temp = seg_b;
						seg_b: motion_pos_temp = seg_c;
						seg_c: motion_pos_temp = seg_d;
						seg_d: motion_pos_temp = seg_e;
						seg_e: motion_pos_temp = seg_f;
						seg_f: motion_pos_temp = seg_a;
						default: motion_pos_temp = seg_a;	
					endcase
					motion_pos <= motion_pos_temp;
				end
				
				TURN_LEFT_2X:
				if(tick10hz)
				begin
					case(motion_pos_temp)
						seg_a: motion_pos_temp = seg_f;
						seg_f: motion_pos_temp = seg_e;
						seg_e: motion_pos_temp = seg_d;
						seg_d: motion_pos_temp = seg_c;
						seg_c: motion_pos_temp = seg_b;
						seg_b: motion_pos_temp = seg_a;
						default: motion_pos_temp = seg_a;	
					endcase
					motion_pos <= motion_pos_temp;
				end
				
				default: motion_pos <= seg_g;
			endcase
		end
	end

	
	//5Hz clock is generated here
	always @(posedge clk)
	begin
		if (ck_count_5Hz == rojobot_cnt_5Hz)
		begin
		    tick5hz <= 1'b1;
		    ck_count_5Hz <= 0;
		end
		else
		begin
		    ck_count_5Hz <= ck_count_5Hz + 1'b1;
		    tick5hz <= 0;
      end
	end

	//1Hz clock is generated here
	always @(posedge clk)
	begin
		if (ck_count_1Hz == rojobot_cnt_1Hz)
		begin
		    tick1hz <= 1'b1;
		    ck_count_1Hz <= 0;
		end
		else
		begin
		    ck_count_1Hz <= ck_count_1Hz + 1'b1;
		    tick1hz 	  <= 0;
      end
	end

	//10Hz clock is generated here
	always @(posedge clk)
	begin
		if (ck_count_10Hz == rojobot_cnt_10Hz)
		begin
		    tick10hz <= 1'b1;
		    ck_count_10Hz <= 0;
		end
		else
		begin
		    ck_count_10Hz <= ck_count_10Hz + 1'b1;
		    tick10hz 	  <= 0;
      end
	end	
endmodule
